Serverless Frameworkで構築するStep Functions
これまで、Step Functionsの構築にCFnやCLI等を利用していましたが、Serverless Frameworkを利用したところ、JSONベースのステートメント言語から開放され、サクッと構築できましたので紹介したいと思います。
Serverless FrameworkでStep Functionsを扱うにはプラグインが必要になります。
過去にStep Functionsプラグインを利用したエントリはありますが、プラグイン等もアップデートされていますので改めてやってみた系のエントリになります。
前提
Serverless Framework自体のインストールや、基本的な利用方法については割愛しています。
その辺りから確認されたい方は、以下が参考になると思います。
- 今から始めるServerless Frameworkで簡単Lambda開発環境の構築
- 初めてのサーバーレスアプリケーション開発 ~Serverless Framework を使ってAWSリソースをデプロイする~
本エントリでは以下バージョンを利用しています。
- serverless 1.48.4
- serverless-step-functions 2.1.0
やってみた
サービス作成
Serverless Frameworkではサービスという単位で複数のリソースを管理しますので、まずはサービスを作成します。
ここでは、サービス用のディレクトリTestStepFunctions
を作成して、サービス名StepFunctionsService
でランタイムはpython3
としました。
$ serverless create --template aws-python3 --name StepFunctionsService --path TestStepFunctions Serverless: Generating boilerplate... Serverless: Generating boilerplate in "/Users/sakamaki.kazuyoshi/awscli/sakamaki.kazuyoshi/TestStepFunctions" _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.48.4 -------' Serverless: Successfully generated boilerplate for template: "aws-python3"
上記コマンドを実行すると、カレントディレクトリにTestStepFunctions
ディレクトリが作成され、配下にServerless Frameworkの定義ファイルserverless.yml
と、テンプレートのpythonスクリプトhandler.py
が作成されます。
$ ls -l total 0 drwxr-xr-x 5 sakamaki.kazuyoshi staff 160 Jul 28 16:15 TestStepFunctions $ ls -lR TestStepFunctions total 16 -rw-r--r-- 1 sakamaki.kazuyoshi staff 497 Jul 28 16:15 handler.py -rw-r--r-- 1 sakamaki.kazuyoshi staff 3162 Jul 28 16:15 serverless.yml
プラグイン インストール
Step Functionsを利用するために以下のプラグイン導入します。
Serverless Frameworkのプラグインはサービスごとに追加され、グローバルには適用されませんので、サービスのルートディレクトリ(ここではTestStepFunctions
)よりインストールを行います。
$ cd TestStepFunctions/ $ npm install --save-dev serverless-step-functions
serverless.yml修正
serverless.yml
はサービス全体の設定を行うためのファイルです。ここでは以下のように定義しました。
service: StepFunctionsService plugins: - serverless-step-functions provider: name: aws runtime: python3.7 region: ap-northeast-1 functions: Function1: name: TestFunction handler: handler.hello stepFunctions: stateMachines: StateMachine1: name: TestStateMachine definition: StartAt: HelloWorld States: HelloWorld: Type: Task Resource: Fn::GetAtt: [Function1LambdaFunction, Arn] End: true
Step Functions周りの設定について説明します。plugins
プロパティでStep Functionsのプラグインを指定し、stepFunctions
プロパティにステートマシンを定義していきます。
ここでは、単一のLambda関数を実行するだけのステートマシンを定義しています。
ステートマシンから実行されるLambda関数は定義ファイル内で作成しており、ステートマシンの定義では、実行するLambda関数のARNが必要になるので、CFn組み込み関数(Fn::GetAtt
)を使用してARNを取得しています。
定義の詳細については、以下をご確認ください。
余談ですが、Serverless Frameworkでどのようにリソース論理名が作成されるか、マニュアルから読み取れなかったので、Fn::GetAtt
に指定するリソース論理名はsls package
等で生成されるCFnテンプレートから確認しました。functions
プロパティ配下のLambda関数論理名(ここではFunction1
)+LambdaFunction
となっていました。
デプロイ
サービスをデプロイします。
$ sls deploy -v Serverless: Packaging service... Serverless: Excluding development dependencies... (省略)
デプロイが完了すると、CFnスタックが作成され、serverless.yml
で定義したLambda、ステートマシンが作成されています。
スタック
Lambda
ステートマシン
動作確認(ステートマシン実行)
デプロイしたステートマシンをServerless Frameworkより実行します。
$ sls invoke stepf --name StateMachine1 . { executionArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:e3fde4c1-c416-4be1-83d1-2ac8f7ae0734', stateMachineArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine', name: 'e3fde4c1-c416-4be1-83d1-2ac8f7ae0734', status: 'SUCCEEDED', startDate: 2019-07-28T07:47:05.951Z, stopDate: 2019-07-28T07:47:06.458Z, input: '{}', output: '{"statusCode": 200, "body": "{\\"message\\": \\"Go Serverless v1.0! Your function executed successfully!\\", \\"input\\": {}}"}' }
実行結果が出力され、ステートマシンを正常に実行することができました。
ステートマシン更新/動作確認
ステートマシン実行時の入力値に応じて、処理分岐するステートマシンに更新してみたいと思います。serverless.yml
を以下に更新しました。ハイライトしている箇所が更新部分です。
以前はステートマシンの更新がサポートされておらず、一度作成したステートマシンは編集できませんでしたが、現在はサポートされていますので、Serverless Frameworkからでも問題なく更新ができます。
service: StepFunctionsService plugins: - serverless-step-functions provider: name: aws runtime: python3.7 region: ap-northeast-1 functions: Function1: name: TestFunction handler: handler.hello stepFunctions: stateMachines: StateMachine1: name: TestStateMachine definition: StartAt: ChoiceState States: ChoiceState: Type: Choice Choices: - Variable: "$.input" StringEquals: "error" Next: Fail Default: HelloWorld HelloWorld: Type: Task Resource: Fn::GetAtt: [Function1LambdaFunction, Arn] Next: Succeed Fail: Type: Fail Succeed: Type: Succeed
デプロイします。
$ sls deploy -v Serverless: Packaging service... Serverless: Excluding development dependencies... (省略)
デプロイが完了するとステートマシンが更新されれました。
ステートマシン実行時のインプットを変え、動作を確認してみたいと思います。
成功
$ sls invoke stepf --name StateMachine1 --data '{"input":"sakana"}' . { executionArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:76401943-7bde-4e90-9acf-ea04d1389ab5', stateMachineArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine', name: '76401943-7bde-4e90-9acf-ea04d1389ab5', status: 'SUCCEEDED', startDate: 2019-07-28T08:14:09.082Z, stopDate: 2019-07-28T08:14:09.634Z, input: '{"input":"sakana"}', output: '{"statusCode": 200, "body": "{\\"message\\": \\"Go Serverless v1.0! Your function executed successfully!\\", \\"input\\": {\\"input\\": \\"sakana\\"}}"}' } HL00257-2:TestStepFunctions sakamaki.kazuyoshi$
失敗
$ sls invoke stepf --name StateMachine1 --data '{"input":"error"}' { executionArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:86dcf2f5-3768-457c-b775-852e08908b65', stateMachineArn: 'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine', name: '86dcf2f5-3768-457c-b775-852e08908b65', status: 'FAILED', startDate: 2019-07-28T08:15:16.756Z, stopDate: 2019-07-28T08:15:16.896Z, input: '{"input":"error"}' } HL00257-2:TestStepFunctions sakamaki.kazuyoshi$
さいごに
ステートマシンの定義にボリュームがでてくると、ステートメント言語(JSONベース)での定義がつらくなってくると思います。また、Step Functionsを利用するほとんどのケースで、Lambdaを利用していると思いますので、一連のデプロイをServerless Frameworkで実施すると簡潔になると思います。CloudWatchイベントの連携等もサクッと定義することができるので、Step Functionsを構築する際はServerless Frameworkの利用を検討してみてはいかがでしょうか。